package user

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/fx"
	"go-admin/base/dao"
	"go-admin/base/utils"

	"go-admin/base/internal/svc"
	"go-admin/base/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type ListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListLogic {
	return &ListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *ListLogic) List(req *types.UserQueryReqDTO) (resp *types.UserRespDTOS, err error) {
	users, err := l.svcCtx.UserModel.FindAll(l.ctx)
	if err != nil {
		fmt.Errorf(err.Error())
		return nil, err
	}
	var userIds []int64
	userIds = utils.Collector[int64](fx.From(func(source chan<- any) {
		for _, user := range users {
			source <- user
		}
	}).Map(func(item any) any {
		iu := item.(*dao.User)
		return iu.Id
	}))

	var us []types.UserRespDTO
	for _, user := range users {
		u := types.UserRespDTO{
			UserID:   user.Id,
			UserName: user.UserName.String,
			UserNum:  user.UserNum.String,
			NickName: user.NickName.String,
		}
		us = append(us, u)
	}
	userRoles, err := l.svcCtx.UserRoleModel.FindUserRolesByUserIds(l.ctx, userIds)
	if err != nil {
		fmt.Errorf(err.Error())
		return nil, err
	}
	var roleIds []int64
	roleIds = utils.Collector[int64](fx.From(func(source chan<- any) {
		for _, userRole := range userRoles {
			source <- userRole
		}
	}).Map(func(item any) any {
		iu := item.(*dao.UserRole)
		return iu.RoleId
	}))
	roles, err := l.svcCtx.RoleModel.FindByRoleIds(l.ctx, roleIds)
	if err != nil {
		fmt.Errorf(err.Error())
		return nil, err
	}

	//for _, u := range us {
	for i := range us {
		u := us[i]
		userID := u.UserID
		var roleRespDTOS []types.RoleRespDTO

		fx.From(func(source chan<- any) {
			for _, userRole := range userRoles {
				source <- userRole
			}
		}).Filter(func(item any) bool {
			userRole := item.(*dao.UserRole)
			return userRole.UserId == userID
		}).Group(func(item any) any {
			userRole := item.(*dao.UserRole)
			return userRole.UserId
		}).ForEach(func(item any) {
			userRoles1 := item.([]interface{})
			//userRoles1 := item.([]*dao.UserRole)
			for _, userRole := range userRoles1 {
				d := userRole.(*dao.UserRole)
				roleId := d.RoleId
				userRoleId := d.Id
				first := fx.From(func(source chan<- any) {
					for _, role := range roles {
						source <- role
					}
				}).Filter(func(item any) bool {
					role := item.(*dao.Role)
					return role.Id == roleId
				}).First()
				role := first.(*dao.Role)
				dto := types.RoleRespDTO{
					RoleID:     roleId,
					UserRoleID: userRoleId,
					RoleName:   role.Name.String,
				}
				roleRespDTOS = append(roleRespDTOS, dto)
			}

		})
		u.Roles = roleRespDTOS
		// todo 注意，go语言中 赋值语句，实际上如果不是指针对象，则赋值后，新对象不影响旧对象
		us[i] = u
	}
	resp1 := &types.UserRespDTOS{
		Data: us,
		Result: types.Result{
			Code: 200,
		},
	}

	return resp1, nil
}
